package com.dcliment.jukebox.controllers
{
	import com.dcliment.elements.MetricsElement;
	import com.dcliment.events.MetricsEvent;
	import com.dcliment.jukebox.display.views.OverlayView;
	import com.dcliment.jukebox.elements.IContent;
	import com.dcliment.jukebox.events.JukeBoxEvent;
	import com.dcliment.jukebox.models.IJukeBoxModel;
	import com.dcliment.jukebox.models.JukeBoxModel;
	import com.dcliment.jukebox.models.OverlayModel;
	import com.dcliment.utils.DisplayObjectUtil;
	import com.greensock.TweenMax;
	import com.greensock.events.LoaderEvent;
	import com.greensock.loading.SWFLoader;
	import com.greensock.loading.display.ContentDisplay;
	
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.MouseEvent;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	
	/**
	 * Controls the overlay.. also helps pause the app if overlay is fired
	 * 
	 * @author dcliment
	 * version 1.1:
	 */	
	public class JukeOverlayController extends EventDispatcher
	{
		//public var OPEN:String = "OPEN";
		public static var CLOSE:String = "CLOSE";
		public static var OVERLAY_INTERACTED:String = "overlay_interacted";
		//
		private var _jukeBoxModel:IJukeBoxModel;
		private var _view:Sprite;
		private var _jukeBoxController:IJukeBox;
		//
		private var _oModel:OverlayModel;
		private var _overlay:OverlayView;
		private var _hitArea:MovieClip;
		//
		private var _swfLoader:SWFLoader;
		//private var _overlaySwf:ContentDisplay;
		private var _overlayRaw:*;
		private var _overlayI:IContent;
		// accessor
		private var _open:Boolean;
		// metrics
		private var _overlayMetric:MetricsElement;
		
		public function JukeOverlayController($model:IJukeBoxModel, $view:Sprite, $controller:IJukeBox)
		{
			_jukeBoxModel 		= $model;
			_view 				= $view;
			_jukeBoxController 	= $controller;
			
			_jukeBoxModel.addEventListener(JukeBoxEvent.PLAY_STATE_CHANGE, onPlayStateChange, false, 0, true);
			
		}
		
		public function setup(m:OverlayModel):void
		{
			_oModel = m;
			
			
		
			
			//---------------------------
			// METRICS
			_overlayMetric = new MetricsElement();
			_overlayMetric.pageElement(_oModel.token);
			
			//--------------------------
			// Overlay from library
			_overlay = DisplayObjectUtil.getLibraryObject(_oModel.clipName) as OverlayView;
			_overlay.label = _oModel.label;
			_view.addChild(_overlay);
			
			// hit area
			_hitArea = _overlay["mHitArea"];
			
	
			if(!_hitArea)
				throw new Error("OverlayController.setup() ERROR :: Library item 'Overlay' is missing an item named 'mHitArea' :: ");
			
			// set position
			reset();
			
			//-------------------------
			// Content
			if(_oModel.contentSrc)
			{
				var appDomain:ApplicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain); // OK.... applicationDomain has to be currDomain for you to cast as IContent
				var cxt:LoaderContext = new LoaderContext(false, appDomain);
				
				//create a SWFLoader that will add the content to the display list at position x:50, y:100 when it has loaded:
				_swfLoader = new SWFLoader(_oModel.contentSrc, {name:"OverlaySwf", container:_overlay, x:_oModel.contentX, y:_oModel.contentY, onComplete:onSwfLoad});
				
				//begin loading
				_swfLoader.load();
			}
			
			//------------------------
			// init
			_hitArea.addEventListener(MouseEvent.CLICK, toggle, false, 0, true);
			_hitArea.buttonMode = true;
		}
		//--------------------------
		/**
		 * take the rawContent of the swf to 
		 *  
		 */		
		private function onSwfLoad(e:LoaderEvent):void
		{
		
			//_overlaySwf = _swfLoader.content;
			_overlayRaw = _swfLoader.rawContent;
			
			_overlayRaw.addEventListener(MetricsEvent.TRACK_ELEMENT, onMetricsCaptured, false, 0, true);
			_overlayRaw.addEventListener(Event.CHANGE, onOverlayInteracted, false, 0, true);
		
			try
			{
				_overlayI = IContent(_overlayRaw); // Has to be done to the raw content
			}
			catch(e:Error)
			{
				throw new Error("OverlayController.onSwfLoad ERROR :: laoded swf = " + _swfLoader.url + " :: Does not extend IContent"); 
			}
			
		}
		//---------------------------
		// public funcitons ~ although not sure if they are ne3eded
		public function reset():void
		{
			TweenMax.killTweensOf(_overlay);
			
			_overlay.x = _oModel.posX;
			_overlay.y = _oModel.posY
				
			_open = false;
			
		}
		
		public function open():void
		{
			_jukeBoxController.pauseApp();
			
			this.tweenOpen();
			
			//bubble to the top
			//_view.setChildIndex();
		
			
		}
		private function tweenOpen():void
		{
			_jukeBoxController.track(_overlayMetric);
			
			if(_overlayI)
			{
				_overlayI.start();
			}
			
		//	_overlay.init();
			
			
			//bubble up this overlay to the top
			_view.setChildIndex(_overlay,_view.numChildren-1);
			TweenMax.to(_overlay, _oModel.tweenSpd, {x:_oModel.tweenX, y:_oModel.tweenY, easing:_oModel.tweenEase});
			_open = true;
	
		}
		
		public function close():void
		{
		
			this.tweenClose();
			
		}
		private function tweenClose():void
		{
			dispatchEvent(new Event(JukeOverlayController.CLOSE));
			
			TweenMax.to(_overlay, _oModel.tweenSpd, {x:_oModel.posX, y:_oModel.posY, easing:_oModel.tweenEase, onComplete:postClose});
			_open = false;
		}
		/**
		 * Runs after tweenClose fires 
		 * 
		 */		
		private function postClose():void
		{
			if(_overlayI)
				_overlayI.reset();
		//	_overlay.reset();
			_jukeBoxController.resumeApp();
		}
		private function toggle(e:MouseEvent):void
		{
			
			TweenMax.killTweensOf(_overlay);
			
			if(_open)
				close();
			else
				open();
		}
		/**
		 * Listens to when the play state changes. Lets say the overlay is open but the 
		 * pause timer runs to the end and the app will continue then the overlay should close()
		 * 
		 * @param e 
		 */		
		private function onPlayStateChange(e:JukeBoxEvent):void
		{
			if(_open && _jukeBoxModel.playState)
				this.tweenClose();
		}
		//---------------------------------------
		// METRICS capture
		private function onMetricsCaptured(e:MetricsEvent):void
		{
			
			_jukeBoxController.track(e.data);
			
			e.stopPropagation();
		}
		//--------------------------------------
		// Overlay interaction
		private function onOverlayInteracted(e:Event):void
		{
			trace('overlay interacted')
			dispatchEvent(new Event(JukeOverlayController.OVERLAY_INTERACTED));
		}
	}
}